<?php
/*
 * Created on 2012-11-21
 * @author yxt
 * To change the template for this generated file go to
 * Window - Preferences - PHPeclipse - PHP - Code Templates
 */
include_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'nl_common.func.php';

class nl_topic{
	const CACHE_TIME_OUT = 300;
	/*
	 * *****************************************************************
	 *
	 *
	 * *****************************************************************
	 */
	/**
	 * 构造 INSERT sql语句
	 * @param array $params  插入数据格式：字段名=>字段值
	 * @param string $table_name 表名字
	 */
	static private function _set_insert_sql($params, $table_name) {
		$ins_sql = 'INSERT INTO `' . $table_name . '` (';
		foreach ($params as $key => $val) {
			//yxt一下一行是对所有的html实体标签和单双引号进行转义
			$val = htmlentities($val, ENT_QUOTES, "UTF-8");
			$ins_key[] =$key;
			$ins_val[] = '\'' . $val . '\'';
		}
		$ins_sql .= implode(',', $ins_key) . ') VALUES(' . implode(',', $ins_val) . ')';
		return $ins_sql;
	}
	/**
	 * 从DB模块获取信息包列表
	 * @param db  DB模块
	 * @param int 机构类型   		可为空  			默认为运营商类型
	 * @param string 机构ID 		可为空 			默认为运营商ID
	 * @param int 查询记录起始位置   	可为空				默认为0
	 * @param int 查询记录条数      	可为空 			默认为20条
	 * @param array	$fields:需要获取的数据库字段一维数组，默认是全部获取
	 * @param string  读取策略     可为空            默认为NL_DC_AUTO   策略类型:NL_DC_AUTO| NL_DC_DB | NL_DC_CACHE
	 * @param array $where:查询的其他where条件
	 * @return *
	 * 			Array 信息包列表
	 * 			FALSE 查询失败
	 * 			TRUE  查询成功，但无数据
	 */
	 static function get_topic_list($dc,$org_type = '',$org_id = '',$since = 0,$num=20,$policy = NL_DC_AUTO,$fields=array(),$where=array()){
	 	//运营商类型为空或者运用商ID为空
	 	if(empty($org_type) ||empty($org_id)){
	 		$org_type = 0;
	 		//获取运营商ID
	 		$org_id = self::_get_carrier_id_by_db($dc->db());
	 	}
	 	switch($policy){
			case NL_DC_AUTO: $result=self::_get_topic_list_cache($dc,$org_type, $org_id, $since, $num,$fields,$policy,$where);break;
			case NL_DC_DB: $result=self::_get_topic_list_db ($dc->db(),$org_type, $org_id, $since, $num,$fields,$where);break;
			case NL_DC_CACHE: $result=self::_get_topic_list_cache($dc,$org_type, $org_id, $since, $num,$fields,$policy,$where);break;
		}
		return $result;
	 }
	/**
	 * 从数据库获取信息包列表
	 * @param DB $db
	 * @param string $org_type
	 * @param string $org_id
	 * @param int $since
	 * @param int $num
	 */
	 static private function _get_topic_list_db($db,$org_type = '',$org_id = '',$since = null,$num=20,$fields=array(),$where){
		if($since===null){
			$limit="";
		}else if(!empty($since)&&empty($num)){
			$limit=" LIMIT {$since}";
		}else{
			$limit=" LIMIT {$since},{$num}";
		}
		if(empty($fields)){
			$field="*";
		}else{
			$field=implode(',',$fields);
		}
	 //判断是否有其他where条件
		$other_where="";
		if(!empty($where)){
			foreach ($where as $k=>$w) {
				$other_where=$other_where.' and '.$k.' '.$w;
			}
		}
		$sql="select {$field} from nns_topic where nns_org_id='{$org_id}' and nns_org_type={$org_type} {$other_where} {$limit}";
		return nl_query_by_db($sql,$db);
	 }
	 /**
	  * 从缓存读取信息包列表
	  * @param DB $db
	 * @param string $org_type
	 * @param string $org_id
	 * @param int $since
	 * @param int $num
	 * @param string $policy:NL_DC_AUTO/NL_DC_CACHE,读取策略如果为NL_DC_AUTO则在没有取到的情况下自动从数据库里面去读，然后缓存起来
	 * @param array $where:查询其他条件
	 * @return true:按照对应策略没有获取到结果集
	 */
	 static private function _get_topic_list_cache($dc,$org_type = '',$org_id = '',$since = null,$num=20,$fields=array(),$policy=NL_DC_AUTO,$where){
		if($since===null){
			$limit="";
		}else if(!empty($since)&&empty($num)){
			$limit=" LIMIT {$since}";
		}else{
			$limit=" LIMIT {$since},{$num}";
		}
		if(empty($fields)){
			$field="*";
		}else{
			$field=implode(',',$fields);
		}
		//判断是否有其他where条件
		$other_where="";
		if(!empty($where)){
			foreach ($where as $k=>$w) {
				$other_where=$other_where.' and '.$k.' '.$w;
			}
		}
		$sql="select nns_id from nns_topic where nns_org_id='{$org_id}' and nns_org_type={$org_type} {$other_where} {$limit}";
		//从缓存中获取ids
		$ids=self::_get_cache_by_sql($dc,$org_id,$sql,$policy);
		//如果从缓存没有读取到ids则返回
		if($ids===false||$ids===true){
			return $ids;
		}
		//转换数组结构
		foreach($ids as &$id){
			$id=$id['nns_id'];
		}
		//根据ids获取结果集,返回
		$result=self::_get_cache_by_ids ($dc,$ids,$fields,$policy);
		return $result;
	 }
	  /**
	  * 根据信息包id获取信息包数据
	  * @param  object  $dc
	  * @param  string  $id
	  * @param array $fields:需要获取的数据字段一维数组
	  * @param  string  $policy 读取策略     可为空            默认为NL_DC_AUTO   策略类型:NL_DC_AUTO| NL_DC_DB | NL_DC_CACHE
	  * @return *
	  * 		array	信息包数据
	  * 		fasle	查询失败
	  * 		true 	查询成功,但无数据
	  */
	 static function get_topic_info($dc,$id,$policy = NL_DC_AUTO,$fields=array()){
	 	switch($policy){
			case NL_DC_AUTO: $result=self:: _get_cache_by_ids ($dc,array($id),$fields,$policy);break;
			case NL_DC_DB: $result=self::_get_topic_info_db ($dc->db(),$id,$fields);break;
			case NL_DC_CACHE: $result=self::_get_cache_by_ids ($dc,array($id),$fields,$policy);break;
		}
		return $result;
	 }
	/**
	 * 根据id直接从数据库中获取记录信息
	 * @param DB $db
	 * @param string $id
	 * @param array $fields:需要获取的数据库字段一维索引数组
	 */
	 static private function _get_topic_info_db($db,$id,$fields=array()){
		if(empty($fields)){
			$field="*";
		}else{
			$field=implode(',',$fields);
		}
		$sql="select {$field} from nns_topic where nns_id='{$id}'";
		return nl_query_by_db($sql,$db);
	 }

	 /**
	  * 统计信息包列表输
	  * @param object $dc
	  * @param int $org_type 	机构类型 可为空 为空时机构类型为运营商
	  * @param string $org_id 	机构id  可为空 为空时机构id为运营商id
	  */
	  static function count_topic_list($dc,$org_type = '',$org_id = ''){
	  	if(empty($org_id)||empty($org_id)){
			$org_id=self::_get_carrier_id_by_db($dc->db());
			$org_type=0;
	  	}
		$sql="select count(1) as c from nns_topic where nns_org_id='{$org_id}' and nns_org_type='{$org_type}'";
		$result=nl_query_by_db($sql,$dc->db());
		if($result===false) return false;
		if($result===true) return 0;
		return $result[0]['c'];
	  }
	  /**
	   * 添加信息包
	   * @param object $db
	   * @param array $params包括（信息包id，信息包名称，机构id，机构类型[，封面图片])[完整的字段=>值]
	   * @param int $policy
	   */
	 static function add_topic($dc,$params,$policy = NL_DC_AUTO){
	 	$params['nns_create_time']=date('Y-m-d H:i:s');
	 	$sql =self::_set_insert_sql($params,'nns_topic');
	 	$result = nl_execute_by_db($sql,$dc->db());
	 	//删除机构缓存key
	 	self::_del_cache_by_org_id($dc,$params['nns_org_id']);
	 	//判断是否需要建立记录缓存
	 	if($policy === NL_DC_AUTO){
			self::_set_cache_by_ids ($dc,array($params['nns_id']));
	 	}
	 	return $result;
	 }
	 /**
	  * 修改信息包
	  * @param object $db
	  * @param array $params
	  * @param
	  */
	  static function modify_topic($dc,$id,$params,$policy = NL_DC_AUTO){
	  	$sql = self::_set_update_sql($params,'nns_topic');
	  	$sql .= ' WHERE nns_id =\''.$id.'\'';
	  	$result = nl_execute_by_db($sql,$dc->db());
	  	//如果删除成功，判断是否需要删除对应的机构缓存和记录缓存
		self::_del_cache_by_ids($dc,array($id),$policy);
	  	if($result&&$policy === NL_DC_AUTO){
			//获取机构id:nns_org_id
			$sql="select nns_org_id from nns_topic where nns_id='{$id}'";
			$result=nl_query_by_db($sql,$dc->db());
			$id=$result[0]['nns_org_id'];
			//删除机构缓存
			self::_del_cache_by_org_id($dc,$id);
	  	}
	  	return $result;
	  }
	  /**
	   * 删除信息包
	   * @param object $dc
	   * @param string $id 信息包id
	   * @param int $policy 读取策略
	   */
	 static function delete_topic($dc,$id,$policy = NL_DC_AUTO){
	 	$db=$dc->db();
	 	//先获取机构id
	 	$sql="select nns_org_id from nns_topic where nns_id='{$id}'";
		$result=nl_query_by_db($sql,$db);
		$org_id=$result[0]['nns_org_id'];

		$sql="delete from nns_topic where nns_id='{$id}'";
		$result=nl_execute_by_db($sql,$db);
		if($result){
			//删除记录缓存
			self::_del_cache_by_ids($dc,array($id),NL_DC_DB);
			//删除机构缓存
			self::_del_cache_by_org_id($dc,$org_id);
		}
		return $result;
	 }
	  /**
	   * 修改 信息包的栏目
	   * @param object $dc
	   * @param string $id
	   * @param string $topic_catagory 信息包的栏目树数据
	   * @param $policy 读取策略
	   */
	 static function update_topic_category($dc,$id,$params,$policy = NL_DC_AUTO){
	  	$db=$dc->db();
	  	$sql = 'UPDATE `nns_topic` SET nns_category=\''.$params.'\' WHERE nns_id =\''.$id.'\'';
	  	$result = nl_execute_by_db($sql,$db);
	  	//如果更新成功则更新记录缓存，同时判断是否删除机构key
	  	self::_del_cache_by_ids($dc,array($id),$policy);
	  	if($policy === NL_DC_AUTO){
			//获取机构id:nns_org_id
			$sql="select nns_org_id from nns_topic where nns_id='{$id}'";
			$r=nl_query_by_db($sql,$db);
			$id=$r[0]['nns_org_id'];
			//删除机构缓存
			self::_del_cache_by_org_id($dc,$id);
	  	}
	  	return $result;
	 }
	 /**
	  *  根据ID批量查询包信息
	  * @param object $dc
	  * @param array  $ids
	  * @param array $fields
	  * @param int    $policy 读取策略     可为空            默认为NL_DC_AUTO   策略类型:NL_DC_AUTO| NL_DC_DB | NL_DC_CACHE
	  */
	 static function get_topic_by_ids($dc,$ids,$policy = NL_DC_AUTO,$fields=array()){
	 	if($dc == NULL || (!is_array($ids))) return FALSE;
		switch($policy){
			case NL_DC_AUTO: $result=self:: _get_cache_by_ids ($dc,$ids,$fields,$policy);break;
			case NL_DC_DB: $result=self::_get_topic_by_ids_db ($dc->db(),$ids,$fields);break;
			case NL_DC_CACHE: $result=self::_get_cache_by_ids ($dc,$ids,$fields,$policy);break;
		}
	 	return $result;
	 }
	 /**
	  * 根据ids直接从数据库获取记录结果集
	  * @param DC $dc
	  * @param array	$ids
	  * @param array 	$fields
	  */
	  static private function _get_topic_by_ids_db($db,$ids,$fields=array()){
		if(empty($fields)){
			$field="*";
		}else{
			$field=implode(',',$fields);
		}
		$id=implode("','",$ids);
		$sql="select {$field} from nns_topic where nns_id in ('{$id}')";
		return nl_query_by_db($sql,$db);
	  }

	  /**
	   * 构造 UPDATE sql语句
	   * @param array $params
	   * @param string $table_name
	   */
	 static private function _set_update_sql($params,$table_name){
	  	$upd_sql = 'UPDATE `'.$table_name.'` SET ';
	  	foreach($params as $key=>$val){
	  		if($key!='nns_category'){
				$val = htmlentities($val, ENT_QUOTES, "UTF-8");
	  		}
	  		$sql_arr[] = $key.'=\''.$val.'\'';
	  	}
	  	$upd_sql .= implode(',',$sql_arr);
	  	return $upd_sql;
	 }
	 /**
	  * 从db 获取信息包列表
	  * @param $db 			db对象
	  * @param $params 		筛选参数
	  * @param $since		记录起始位置
	  * @param $num 		取得记录数量
	  */
	 static private function _get_topic_list_by_db($db,$params,$since,$num){
	 	if($db === NULL) return FALSE;

	 	$sql = "SELECT * FROM `nns_topic` WHERE ";
	 	$sql .= self::_set_where($params,'AND');
	 	$sql .= " ORDER BY nns_create_time DESC LIMIT $since,$num";

		$result = nl_query_by_db($sql,$db);

		if(count($result) >0){
			return $result;
		}else{
			return TRUE;
		}
	 }

	 /**
	  * 从db获取运营商id
	  * @param object $db
	  */
	  static private function _get_carrier_id_by_db($db){
	  		include_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'system/system.class.php';
	 		$carrier_info = nl_system::get_carrier_id($db);
	 		if($carrier_info === FALSE) return FALSE;
	 		$org_id = $carrier_info['0']['nns_id'];
	 		return isset($carrier_info['0'])?$carrier_info['0']['nns_id']:TRUE;
	  }

	 /**
	  * 根据ids设置缓存记录
	  * @param DC $dc
	  * @param array $ids
	  */
	  static private function _set_cache_by_ids ($dc,$ids=array()) {
	  	if(!$dc->is_cache_enabled()) return null;
	  	$db=$dc->db();
	  	$cache=$dc->cache();
		//循环从数据库获取记录，然后存入缓存
		if(is_array($ids)){
			foreach($ids as $id){
				$sql="select * from nns_topic where nns_id='{$id}'";
				$result=nl_query_by_db($sql,$db);
				if($result!==true&&$result!==false){
					$cache->set('nns_topic_'.$id,$result,self::CACHE_TIME_OUT);
				}elseif($result===false){
					return false;
				}
			}
		}
		return false;
	}
	/**
	 * 根据ids获取记录缓存
	 * @param DC $dc
	 * @param array $ids
	 * @param array 需要获取的数据字段
	 * @param string 是否在没有获取到数据的情况下从数据库读取并存入缓存
	 */
	  static private function _get_cache_by_ids ($dc,$ids=array(),$fields=array(),$policy = NL_DC_AUTO) {
			$cache=$dc->cache();
			$db=$dc->db();
			$data=array();
			if(is_array($ids)){
			$i=0;
			foreach($ids as $id){
				if($dc->is_cache_enabled()){
					//获取缓存，成功返回二维数组
					$result="";
					$result=$cache->get('nns_topic|#'.$id);
					if($result){//缓存获取成功
						if(!empty($fields)){
							foreach($fields as $field){
								$data[$i][$field]=$result[0][$field];
							}
						}else{
							$data[$i]=$result[0];
						}
					}else if($policy===NL_DC_AUTO){//缓存获取失败，需要从数据库获取
						$sql="select * from nns_topic where nns_id='{$id}'";
						$result = nl_query_by_db($sql, $db);
						self::_set_cache_by_ids($dc,$arr=array($id));
						if($result!==false&&$result!==true){
							if(!empty($fields)){
								foreach($fields as $field){
									$data[$i][$field]=$result[0][$field];
								}
							}else{
								$data[$i]=$result[0];
							}
						}
					}
				}else if($policy===NL_DC_AUTO){
					$sql="select * from nns_topic where nns_id='{$id}'";
					$result = nl_query_by_db($sql, $db);
					if($result!==false&&$result!==true){
						if(!empty($fields)){
							foreach($fields as $field){
								$data[$i][$field]=$result[0][$field];
							}
						}else{
							$data[$i]=$result[0];
						}
					}
				}
				$i++;
			}
			return $data;
		}else{
			return false;
		}
	  }
	/**
	 * 根据ids删除记录缓存
	 * @param DC $dc
	 * @param array $ids
	 * @param string 是删除还是更新缓存默认是删除，如果是NL_DC_AUTO则为更新
	 */
	 static private function _del_cache_by_ids($dc,$ids=array(),$policy=NL_DC_AUTO){
	 	if(!$dc->is_cache_enabled()){
	 		return null;
	 	}
	 	$cache=$dc->cache();
		if(is_array($ids)){
			if($policy===NL_DC_AUTO){
				self::_set_cache_by_ids ($dc,$ids);
			}elseif($policy===null){
				foreach($ids as $id){
					$cache->delete('nns_topic|#'.$id);
				}
			}
		}else{
			return false;
		}
	 }
	/**
	 * 根据机构id和sql来设置缓存ids
	 * @param DC $dc
	 * @param string $org_id
	 * @param string $sql
	 * 数据库执行失败返回false，执行没有结果或者设置成功返回true
	 */
	 static private function _set_cache_by_sql($dc,$org_id,$sql){
	 	if(!$dc->is_cache_enabled()){
	 		return null;
	 	}
		$cache=$dc->cache();
		$db=$dc->db();
		//获取符合条件的ids结果集
		$result=nl_query_by_db($sql,$db);
		if($result===false||$result===true){
			return $result;
		}
		$sql=md5($sql);
		//获取机构key
		$key=$cache->get('topic|#'.$org_id);
		//获取失败重新设置
		if(!empty($key)){
			$key=$org_id;
			$cache->set('topic|#'.$org_id,$key);
		}
		return $cache->set($key.'|#'.$sql,$result);
	 }
	/**
	 * 根据机构id和sql来获取缓存ids
	 * @param DC $dc
	 * @param string $org_id
	 * @param string $sql
	 * 数据库执行失败返回false，执行没有结果返回true，有结果集，返回二维ids数组，缓存获取失败返回null
	 */
	 static private function _get_cache_by_sql($dc,$org_id,$sql,$policy=NL_DC_AUTO){
		$db=$dc->db();
		if($dc->is_cache_enabled()){
			$cache=$dc->cache();
			//获取机构key
			$key=$cache->get('topic|#'.$org_id);
			$result=$cache->get($key.'|#'.$sql);
			//如果获取失败，判断是否是只从缓存里读取，如果是返回，不是继续
			if(empty($result)){
				if($policy!=NL_DC_AUTO){
					return null;
				}else{
					//如果没有找到，则读取数据并设置缓存
					self::_set_cache_by_sql($dc,$org_id,$sql,$policy=NL_DC_AUTO);
					//为了防止缓存没有打开就不存缓存里获取，而是从数据库获取
					$result=nl_query_by_db($sql,$dc->db());
				}
			}
		}elseif($policy===NL_DC_AUTO){
			$result=nl_query_by_db($sql,$dc->db());
		}else{
			$result=null;
		}
		return $result;
	 }
	 /**
	  * 根据机构id删除机构的缓存
	  * @param DC $dc
	  * @param string $org_id
	  * 数据库执行失败返回false，执行没有结果或者设置成功返回true
	  */
	  static private function _del_cache_by_org_id($dc,$org_id){
	  	if(!$dc->is_cache_enabled()){
	 		return null;
	 	}
		$dc->cache()->delete('topic|#'.$org_id);
	  }
/**
 * 根据包id和栏目id获取栏目下的所有子孙栏目信息
 * @param string $topic_id
 * @param string $category_id，可以不传递，不传表示获取包下的所有栏目信息
 * @return array $data_arr:返回子孙栏目组成的一维索引数组，米有返回null,如果包没有栏目则返回null
 */
 static public function get_son_category_by_category_id($dc,$topic_id,$category_id=null){
	//首先获取包栏目信息
	$topic_info=self::get_topic_info($dc,$topic_id,NL_DC_AUTO,array("nns_category"));
	$category_info=$topic_info[0]['nns_category'];
	if(empty($category_info)) return null;
	$dom = new DOMDocument('1.0', 'utf-8');
	$dom->loadXML($category_info);
	$nodelist=$dom->getElementsByTagName('category');
	//因为当删除完毕信息包下的所有子栏目之后数据库并没有设为null所以这个时候需要判断是否有子栏目
	if($nodelist->length<1) return null;
	//到这一步说明有子栏目
	if(!empty($category_id)){//如果传递了栏目id
		foreach($nodelist as $node){
			if($node->getAttribute('id')==$category_id){
				$c_item=$node;//获取该栏目的子孙xml
				break;
			}
		}
	}else{//如果没有传递栏目id
		$c_item=$dom->getElementsByTagName('topic')->item(0);
	}
	$data_arr=array();
	//递归获取子孙元素信息
	self::get_one_son_node_info($c_item,$data_arr);
	return $data_arr;
 }
 /**
  * 获取指定xml节点的一级孩子节点的id和name
  * @param DOMNode $node
  * @param array $node_arr:保存的二维关联数组
  * @return null：因为传递进来的是地址就不用返回数据了。
  */
  static private function get_one_son_node_info ($node,&$node_arr) {
	//首先判断是否有孩子节点
	$child_nodes=$node->childNodes;
	if($child_nodes->length>0){
		foreach($child_nodes as $child){
			self::get_one_son_node_info($child,$node_arr);
		}
	}
	if($node->hasAttributes()){
		$node_arr[]=array('id'=>$node->getAttribute('id'),'name'=>$node->getAttribute('name'));
	}
    return;
}
}
?>